package com.vhall.component.framework.common.utils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 时间相关工具类
 *
 * @author yuanzh
 */
public class TimeUtil {

    private TimeUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 毫秒转秒
     *
     * @param ts
     * @return
     */
    public static int getSecondsFromMills(long ts) {
        return (int) TimeUnit.MILLISECONDS.toSeconds(ts);
    }

    /**
     * 获取当前秒级时间截
     *
     * @return
     */
    public static int getCurrentSeconds() {
        return getSecondsFromMills(System.currentTimeMillis());
    }

    /**
     * 秒转毫秒
     *
     * @param ts
     * @return
     */
    public static long getMillsFromSeconds(int ts) {
        return TimeUnit.SECONDS.toMillis(ts);
    }

    /**
     * 某个时间截对应的当天0点时间截
     *
     * @param ts 时间截
     * @return
     */
    public static long getZeroTsOfDay(long ts) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(ts);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTimeInMillis();
    }

    /**
     * 某时区某天的零点时间戳，转换成东八区零点时间戳
     *
     * @param ts
     * @return
     */
    public static int otherZeroTsToGMT8ZeroTs(int ts) {
        final int s = getCurrentSeconds() % (24 * 3600);
        final int m = ts % (24 * 3600);
        if (s != m) {
            int result = ts - (m - 16 * 3600);
            if (m >= 21 * 3600 && m <= 23 * 3600) {
                result += 24 * 3600;
            }
            return result;
        } else {
            return ts;
        }

    }

    public static final long ONE_WEEK_TS = TimeUnit.DAYS.toMillis(7);
    public static final long ONE_DAY_TS = TimeUnit.DAYS.toMillis(1);

    /**
     * 求2个时间截之间相关的周数和余下的天数
     *
     * @param startTs
     * @param endTs
     * @return
     */
    public static Pair<Long, Long> getWeeksDaysFromDiff(long startTs, long endTs) {
        if (startTs < endTs) {
            long diff = endTs - startTs;

            long weeks = diff / ONE_WEEK_TS;
            long daysTs = diff % ONE_WEEK_TS;
            long days = daysTs / ONE_DAY_TS;
            if (daysTs % ONE_DAY_TS > 0) {
                days++;
            }
            return Pair.makePair(weeks, days);
        }
        return null;
    }

    /**
     * 当天0点时间截
     *
     * @return
     */
    public static long getCurrentDayZeroTs() {
        return getZeroTsOfDay(System.currentTimeMillis());
    }

    public static final String genMMSSStr(int seconds) {
        int minute = seconds / 60;
        int sec = seconds % 60;
        StringBuilder s = new StringBuilder();
        if (minute > 0) {
            s.append(minute).append("分钟");
        }
        if (sec > 0) {
            s.append(sec).append("秒");
        }
        return s.toString();
    }

    /**
     * 查星期几
     *
     * @param dayOfWeek 星期中的第几天，从Calendar.DAY_OF_WEEK中来
     * @return
     */
    public static String getWeekText(int dayOfWeek) {
        switch (dayOfWeek) {
            case 3:
                return "二";
            case 4:
                return "三";
            case 5:
                return "四";
            case 6:
                return "五";
            case 7:
                return "六";
            case 1:
                return "日";
            default:
                return "一";
        }
    }

    /**
     * 查星期几
     *
     * @param timestamp 时间截，单位：毫秒
     * @return
     */
    public static String getWeekText(long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        return getWeekText(calendar.get(Calendar.DAY_OF_WEEK));
    }

    /**
     * 获取小时
     *
     * @param ts 秒
     * @return
     */
    public static int getHour(int ts) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(getMillsFromSeconds(ts));
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获取小时
     *
     * @param timestamp 毫秒
     * @return
     */
    public static int getHour(long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获取星期数据
     *
     * @param date
     * @return
     */
    public static short getWeekDate(Date date) {
        Short[] week = {7, 1, 2, 3, 4, 5, 6};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int number = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (number < 0) {
            number = 0;
        }

        return week[number];
    }

    /**
     * 获取本周一的时间戳
     *
     * @param ts
     * @return
     */
    public static int getWeekTs(int ts) {
        long millionSeconds = TimeUtil.getMillsFromSeconds(ts);

        Date date = new Date(millionSeconds);
        short number = getWeekDate(date);
        millionSeconds = millionSeconds - TimeUnit.DAYS.toMillis(number - 1L);

        return TimeUtil.getSecondsFromMills(TimeUtil.getZeroTsOfDay(millionSeconds));
    }

    /**
     * 获得当天零点时间戳
     *
     * @param ts
     */
    public static int getDayTs(int ts) {
        long millionSeconds = TimeUtil.getMillsFromSeconds(ts);
        return TimeUtil.getSecondsFromMills(TimeUtil.getZeroTsOfDay(millionSeconds));
    }

    /**
     * 获取东8区当天零点时间戳
     *
     * @param ts
     * @return
     */
    public static int getGMT8DayTs(int ts) {
        return otherZeroTsToGMT8ZeroTs(ts);
    }

    /**
     * 通过预产期计算孕期
     *
     * @param expectedBornTs
     * @return
     */
    public static Pair<Integer, Integer> calcPregWeekAndDay(int expectedBornTs) {
        int currentTs = getCurrentSeconds();
        int week;
        int day;
        if (currentTs < expectedBornTs) {
            int dayCount = (int) Math.ceil((expectedBornTs - currentTs) / (1.0 * 24 * 3600));
            week = 39 - dayCount / 7;
            day = 7 - dayCount % 7;
        } else {
            int dayCount = (int) Math.floor((currentTs - expectedBornTs) / (1.0 * 24 * 3600));
            week = dayCount / 7;
            day = dayCount % 7;
            if (0 == day) {
                week += 39;
                day = 7;
            } else {
                week += 40;
            }
            if (week >= 42) {
                week = 41;
                day = 7;
            }
        }
        if (7 == day) {
            ++week;
            day = 0;
        }
        return Pair.makePair(week, day);
    }

    public static String secondToStringDate(long second) {
        Date date = new Date(second * 1000);
        SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd");
        return format.format(date);
    }

}
